package dinnerSimulation;

/**
 * Agent Dynamic_1
 * @author Caterina
 *
 * - B: dinamico 1
 *  - 1 istante (turno) per fare un'azione
 *  - ogni k passi un oggetto a caso si muove, ma solo verso una 
 *   casella a caso nella stessa stanza.
 *
 *
 */

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;

import dlvwrapper.DlvWrapper;


public class AgentCiccioD_1 extends AgentCiccio {


	private List<Coord> meal_ready_actions = new ArrayList<Coord>();
	private List<Coord> suit_up_actions = new ArrayList<Coord>();
	private List<Coord> take_meal_actions = new ArrayList<Coord>();
	private List<Coord> table_ready_actions = new ArrayList<Coord>();
	private List<Coord> flowers_taken_actions = new ArrayList<Coord>();
	private List<Coord> entrance_actions = new ArrayList<Coord>()			;
	private int countMoves = 0;
	private Coord currentPos;

	private List<Coord> actions;
	private DlvWrapper dlvwrapper;
	private int nextPos;
	private int nextRoom;
	public boolean init;
	private String subgoal;
	private String initial_plan;
	private String doors, adj;
	


	public AgentCiccioD_1(int x, int y, int opBound) {
		super(x, y, opBound);

		init = false;
		cal = false;
		cal_suitUp = false;
		cal_takeFlow = false;
		this.dlvwrapper = new DlvWrapper();
		this.initial_plan = "\n";
		this.doors ="\n";
		this.adj ="\n";
		
		
		
	}



	


	/**
	 * @return true if the agent has reached the goal
	 */
	public boolean goalReached() {
		return goalReached;
	}

	/**
	 * Make the agent perceives from environment
	 * 
	 * @param perception
	 *            current perception from the environment
	 */
	public void perceives(Perception perception) {
		this.perception = perception;
	}

	@Override
	public void update() {
		
		if (init){
			
			if (!this.MEAL_READY) 
				execute_MealReady();
			
			if (!this.SUIT_UP && MEAL_READY) {
				execute_SuitUP();
			}
			
			if (!this.TAKE_MEAL && SUIT_UP) {
				execute_TakeMeal();
			}
			
			if (!this.TABLE_READY && this.TAKE_MEAL) {
				execute_TableReady();
			}
				
			
			
			if (!this.FLOWERS_TAKEN && TABLE_READY) {
				execute_TakeFlowers();
			}
			
			if (!this.ENTRANCE && FLOWERS_TAKEN) {	
				execute_WaitRenata();
			
			}
			
			
		}else {
			print_back();
			print_initial(x, y);
			init = true;
		}

	}

	private void execute_WaitRenata() {
		
		if(entrance_actions.isEmpty() && !cal){
			print_initial(currentPos.x, currentPos.y);
				entrance_actions = dlvwrapper.getPlan("wait_renata");
		
			cal = true;
			actions = entrance_actions;
			currentPos = actions.get(actions.size() - 1);
			countMoves += entrance_actions.size();
			subgoal = "WAIT_RENATA";
		}
		
		executeAction();
		
	}






	private void execute_TakeFlowers() {
	if(flowers_taken_actions.isEmpty() && !cal){
			print_in_flowers(currentPos.x, currentPos.y);
			flowers_taken_actions = dlvwrapper.getPlan("take_flowers");
			cal = true;
			
			actions = flowers_taken_actions;
			currentPos = actions.get(actions.size() - 1);
			countMoves += flowers_taken_actions.size();
			subgoal = "FLOWERS_TAKEN";
		}
		
		executeAction();
		
	}






	private void execute_TableReady() {
		if(table_ready_actions.isEmpty() && !cal){
			print_initial(currentPos.x, currentPos.y);
			table_ready_actions = dlvwrapper.getPlan("table_ready");
			cal = true;
			
			actions = table_ready_actions;
			currentPos = actions.get(actions.size() - 1);
			countMoves += table_ready_actions.size();
			subgoal = "TABLE_READY";
		}
		
		executeAction();
		
	}






	private void execute_TakeMeal() {
		if(take_meal_actions.isEmpty() && !cal){
			
			print_initial(currentPos.x, currentPos.y);
			take_meal_actions = dlvwrapper.getPlan("take_meal");
			cal = true;
			actions = take_meal_actions;
			currentPos = actions.get(actions.size() - 1);
			countMoves += take_meal_actions.size();
			subgoal = "TAKE_MEAL";
		}
		
		executeAction();
		
	}






	private void execute_SuitUP() {
		if(suit_up_actions.isEmpty() && !cal){
		
			print_in_smoking(currentPos.x, currentPos.y);
			suit_up_actions = dlvwrapper.getPlan("dress_up");
			actions = suit_up_actions;
			currentPos = actions.get(actions.size() - 1);
			cal=true;
			countMoves += suit_up_actions.size();
			subgoal = "DRESS_UP";
		}
		
		executeAction();
		
	}






	/**
	 * Print the list of agent actions
	 */
	public void showActions() {
		for (int i = 0; i < actionList.size(); i++)
			System.out.println(actionList.get(i).type);
	}

	/**
	 * Add the current action to the agent action list
	 * 
	 * @return current action of the agent
	 */
	public Action.Type action() {
		if (actionList.size() == 0) {
			perception.floor.set(x, y, dinnerSimulation.Square.Type.CLEAN);
		}
		actionList.add(new Action(currAction, x, y));
		// System.out.println("currAction ->  x= " + x + " y= " + y);
		return currAction;
	}

	/**
	 * 
	 * @param x
	 *            room di ciccio
	 * @param y
	 *            pos di ciccio
	 */

	public void print_back() {
		String obj = "\n";
		String room = "\n";
		String position = "\n";
		obj += "object(ciccio). object(meal). object(flowers). object(table). "
				+ "object(smoking). object(entrance).";

		for (int k = 0; k < perception.floor.width; k++)
			position += "\nposition(" + (k + 1) + ").";

		for (int i = 0; i < perception.floor.length; i++) {
			room = room + "room(" + (i + 1) + ","
					+ perception.floor.room[i].toString().toLowerCase()
					+ " ).\n";

			for (int j = 0; j <= perception.floor.width; j++) {
				if (perception.floor.get(i-1, j) == Square.Type.DOOR && perception.floor.room[i] == Floor.roomType.ENTRANCE){
					perception.floor.set(i, j, Square.Type.ENTRANCE);
					System.out.println("Square type settato Entrance");
				}
			}
			
		}
		printDoor();
		/*int c =0;
		while(c<4){
			perceives(perception);
			c = printDoor();
			
			
		}
		System.out.println("while c = " + c);
		
		System.out.println("doors " + this.doors);
*/
		try {
			// Create file

			FileWriter fstream = new FileWriter("dlv/ciccio_pasticcio_back.dl");
			BufferedWriter out = new BufferedWriter(fstream);
			out.write("%ciccio_pasticcio_back.dl");
			out.write(obj + room + position + doors + adj);

			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}

	}
	
	public int printDoor(){
		int count =0;
		int pos;
		for (int i = 0; i < perception.floor.length; i++) {
			int rpos = i + 1;
			for (int j = 0; j <= perception.floor.width; j++) {
				pos = j + 1;
		if (perception.floor.get(i, j) == Square.Type.DOOR
				&& perception.floor.room[i] != Floor.roomType.ENTRANCE
				&& !(j == (y + 1) && perception.floor.room[x] == perception.floor.room[i])) {
			count++;
			doors = doors
					+ "\ndoor_at("
					+ perception.floor.room[i].toString().toLowerCase()
					+ ","
					+ perception.floor.room[i + 1].toString()
							.toLowerCase()
					+ ","
					+ pos
					+ ").\n"
					+ "door_at("
					+ perception.floor.room[i + 1].toString()
							.toLowerCase() + ","
					+ perception.floor.room[i].toString().toLowerCase()
					+ "," + pos + ").\n";
			adj += "\nadjacent(" + rpos + "," + pos + "," + (rpos + 1)
					+ "," + pos + ").";
			adj += "\nadjacent(" + (rpos + 1) + "," + pos + "," + rpos
					+ "," + pos + ").";
		}
		if (pos < perception.floor.width) {
			adj += "\nadjacent(" + rpos + "," + pos + "," + rpos + ","
					+ (pos + 1) + ").";
			adj += "\nadjacent(" + rpos + "," + (pos + 1) + "," + rpos
					+ "," + pos + ").";
		}
		
			}
		}
		return count;
	}
	

	
	
	
	public void print_initial(int x, int y) {

		String res = "\n";
		String ciccioPos = "\n";
		int pos;

		ciccioPos = ciccioPos+ "at(ciccio,"
				+ perception.floor.room[x].toString().toLowerCase() + ","
				+ (y + 1) + ").\n";

		for (int i = 0; i < perception.floor.length; i++) {
			System.out.println("ROOM  " + i + perception.floor.room[i].toString());
			for (int j = 0; j <= perception.floor.width; j++) {
				pos = j + 1;

			/*	if (perception.floor.room[i] == Floor.roomType.BEDROOM
						&& perception.floor.get(i, j) == Square.Type.SMOKING) {
					res = res + "at("
							+ Square.Type.SMOKING.toString().toLowerCase()
							+ ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";
				} 

				if (perception.floor.get(i, j) == Square.Type.FLOWERS) {
					res = res + "at("
							+ Square.Type.FLOWERS.toString().toLowerCase()
							+ ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";
				}*/

				if (perception.floor.get(i, j) == Square.Type.TABLE) {
					res = res + "at("
							+ Square.Type.TABLE.toString().toLowerCase() + ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";
				}

				if (perception.floor.get(i, j) == Square.Type.MEAL)
					res = res + "at("
							+ Square.Type.MEAL.toString().toLowerCase() + ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";

			
			
				if (perception.floor.room[i] == Floor.roomType.ENTRANCE) {
					if (perception.floor.get(i-1, j) == Square.Type.DOOR)
				
					res = res + "at("
							+ Square.Type.ENTRANCE.toString().toLowerCase()
							+ ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";
				}
				}
				initial_plan = res;
	
		}
		//System.out.println(res);

		try {
			// Create file

			FileWriter fstream = new FileWriter(
					"dlv/ciccio_pasticcio_initial.plan");
			BufferedWriter out = new BufferedWriter(fstream);
			out.write("%ciccio_pasticcio_initial.plan");
			out.write("\ninitially:" + ciccioPos + res);

			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}
	}

	
	private void print_in_flowers(int x, int y){
		String flowers ="\n";
		
		String ciccioPos = "\n";
		ciccioPos = ciccioPos+ "at(ciccio,"
				+ perception.floor.room[x].toString().toLowerCase() + ","
				+ (y + 1) + ").\n";
		
		
		for (int i = 0; i < perception.floor.length; i++) {
			int pos;
			for (int j = 0; j <= perception.floor.width; j++) {
				pos = j + 1;

				if (perception.floor.get(i, j) == Square.Type.FLOWERS) {
					flowers = flowers + "at("
							+ Square.Type.FLOWERS.toString().toLowerCase()
							+ ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";
				}
			}
		}
		
		
		
		
		try {
			// Create file

			FileWriter fstream = new FileWriter(
					"dlv/ciccio_pasticcio_initial.plan");
			BufferedWriter out = new BufferedWriter(fstream);
			out.write("%ciccio_pasticcio_initial.plan");
			out.write("\ninitially:" + ciccioPos + flowers);

			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}
	}
	
	
	
	
	
	private void print_in_smoking(int x, int y){
		String smok ="\n";
		
		String ciccioPos = "\n";
		ciccioPos = ciccioPos+ "at(ciccio,"
				+ perception.floor.room[x].toString().toLowerCase() + ","
				+ (y + 1) + ").\n";
		
		
	/*	for (int i = 0; i < perception.floor.length; i++) {
			int rpos = i + 1;
			int pos;
			for (int j = 0; j <= perception.floor.width; j++) {
				pos = j + 1;

				if (perception.floor.room[i] == Floor.roomType.BEDROOM
						&& perception.floor.get(i, j) == Square.Type.SMOKING) {
					smok = smok+ "at("
							+ Square.Type.SMOKING.toString().toLowerCase()
							+ ","
							+ perception.floor.room[i].toString().toLowerCase()
							+ "," + pos + ").\n";
				} 
			}
		}*/
		
		Coord c = perception.floor.search(Square.Type.SMOKING);
		smok = smok + "at("
				+ Square.Type.SMOKING.toString().toLowerCase()
				+ ","
				+ perception.floor.room[c.x].toString().toLowerCase()
				+ "," + (c.y+1) + ").\n";
		
		
		initial_plan = "\ninitially:" + initial_plan + smok;
	//	System.err.println("INITIAL PLAN : " + initial_plan);
		try {
			// Create file

			FileWriter fstream = new FileWriter(
					"dlv/ciccio_pasticcio_initial.plan");
			BufferedWriter out = new BufferedWriter(fstream);
			out.write("%ciccio_pasticcio_initial.plan");
			out.write("\ninitially:"  + smok + ciccioPos);

			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}
	}
	
	
	
	public void execute_MealReady(){
		
		if(meal_ready_actions.isEmpty() && !cal){
			meal_ready_actions = dlvwrapper.getPlan("prepare_meal");
			
			cal = true;
			actions = meal_ready_actions;
			currentPos = actions.get(actions.size() - 1);
			countMoves += meal_ready_actions.size();
			subgoal = "PREPARE_MEAL";
		}
		
		executeAction();

	}

	
	
	
	public void executePlan() {
	

		if (countMoves < stepValue) {
			currentPos = meal_ready_actions.get(meal_ready_actions.size() - 1);
			print_initial((currentPos.x), (currentPos.y));
			suit_up_actions = dlvwrapper.getPlan("dress_up");
			countMoves += suit_up_actions.size();
		}

		if (countMoves < stepValue) {

			currentPos = suit_up_actions.get(suit_up_actions.size() - 1);
			print_initial((currentPos.x), (currentPos.y));
			take_meal_actions = dlvwrapper.getPlan("take_meal");
			countMoves += suit_up_actions.size();
		}

		if (countMoves < stepValue) {
			currentPos = take_meal_actions.get(take_meal_actions.size() - 1);
			print_initial((currentPos.x), (currentPos.y));
			table_ready_actions = dlvwrapper.getPlan("table_ready");
			countMoves += table_ready_actions.size();
		}

		if (countMoves < stepValue) {
			currentPos = table_ready_actions
					.get(table_ready_actions.size() - 1);
			print_initial((currentPos.x), (currentPos.y));
			flowers_taken_actions = dlvwrapper.getPlan("take_flowers");
			countMoves += flowers_taken_actions.size();
		}

		if (countMoves < stepValue) {
			currentPos = flowers_taken_actions
					.get(flowers_taken_actions.size() - 1);
			print_initial((currentPos.x), (currentPos.y));
			entrance_actions = dlvwrapper.getPlan("wait_renata");
			countMoves += entrance_actions.size();
		}
		if (countMoves>stepValue){
			System.err.println("Error: Il pathlength � pi� lungo dello stepvalue ");
		
		}

	}

	public void executeAction() {
		
		// l'energia viene decrementata nel mainloop
		if (energy > 0) {
			if (actions.size() == 0) {
				
				if(subgoal == "PREPARE_MEAL") {
		
					currAction = Action.Type.PREPARE_MEAL;
					cal = false;
					cal_suitUp = true;
					System.out.println("SUB PREPARE MEAL");
				}
				
				if(subgoal == "DRESS_UP") {
					
					currAction = Action.Type.DRESS_UP;
					cal = false;
					System.out.println("SUB DRESS_UP");
				}
					
				if(subgoal == "TAKE_MEAL") {
					
					currAction = Action.Type.TAKE_MEAL;
					cal = false;
					System.out.println("SUB TAKE_MEAL");
				}
				
					if(subgoal == "TABLE_READY") {
					
					currAction = Action.Type.TABLE_READY;
					cal = false;
					cal_takeFlow = true;
					System.out.println("TABLE_READY");
				}
					if(subgoal == "FLOWERS_TAKEN") {
						
						currAction = Action.Type.TAKE_FLOWERS;
						cal = false;
						System.out.println("TAKE_FLOWERS");
					}
					if(subgoal == "WAIT_RENATA") {
						
						currAction = Action.Type.WAIT_RENATA;
						cal = false;
						System.out.println("WAIT_RENATA");
					}

			} else {

				nextPos = actions.get(0).y;
				nextRoom = actions.get(0).x;
				actions.remove(0);
				moveCiccio(nextPos, nextRoom);

			}
			
			if(super.ENTRANCE){
				goalReached = true;
			}

			

		}else{
			died = true;
		}
		
		
		
		
		/*
		 * for (int i = 0; i < meal_ready_actions.size(); i++) {
		 * System.out.println("*********************************");
		 * System.out.println("moves : \n" + i +
		 * meal_ready_actions.get(i).toString());
		 * 
		 * }
		 */
	}

	@Override
	public void setCurrentPosition(int room, int pos) {
		this.x = room;
		this.y = pos;
	}

	public void moveCiccio(int nextPos, int nextRoom) {
		System.out.println("currpos -> x= " + x + " y= " + y);
		System.out.println(" nextRoom -> " + nextRoom + " nextPos ->  "
				+ nextPos);
		if (this.x == nextRoom) {

			if (nextPos == (y + 1) && nextPos <= perception.floor.width) {
				System.out.println("executeAction == EAST ");
				currAction = Action.Type.EAST;
			}

			if (nextPos == (y - 1) && nextPos >= 0) {
				System.out.println("executeAction == WEST ");
				currAction = Action.Type.WEST;
			}
		}

		if (this.y == nextPos) {
			if (nextRoom == (x - 1) && nextRoom >= 0) {
				System.out.println("executeAction == NORTH ");
				currAction = Action.Type.NORTH;
			}

			if (nextRoom == (x + 1) && nextRoom <= perception.floor.length) {
				System.out.println("executeAction == SOUTH ");
				currAction = Action.Type.SOUTH;
			}
		}

	}
	

}
